Strict 
#Rem
	Header: - Entity class
#End
Import mojo
Import agfx

Global var1:Float
Global var2:Float
Global var3:Float


#Rem
	summary: TEntity
#End
Class TEntity

	Public
	
	#Rem
		summary: - entity name
	#End
	Field name:String				= "noname_entity"
	
	#Rem
		summary: - visibility state
	#End
	Field visible:Bool				= True
	
	#Rem
		summary: - enable state
	#End
	Field enable:Bool				= True
	
	#Rem
		summary: - position
	#End
	Field position:TVector2 		= New TVector2(0,0)
	
	#Rem
		summary: - old position
	#End
	Field old_position:TVector2 		= New TVector2(0,0)

	#Rem
		summary: - roattion
	#End
	Field rotation:Float			= 0	
	
	#Rem
		summary: - direction vector
	#End
	Field direction:TVector2		= New TVector2(0,-1)
	
	#Rem
		summary: - base direction
	#End
	Field base_direction:TVector2	= New TVector2(0,-1)
	
	#Rem
		summary: - size
	#End
	Field size:TVector2 			= New TVector2(32,32)
	
	#Rem
		summary: - radius
		used for circle collision check
	#End
	Field radius:Float				= 32/2.0
	
	#Rem
		summary: - collision box
	#End
	Field collision:TBBox			= New TBBox()
	
	#Rem
		summary: - collision type for handling collision
	#End
	Field collision_type:Int        = COLLISION_TYPE_NONE
	#Rem
		summary: - speed
		used for motion calc
	#End
	Field speed:Float				= 1.0
	
	#Rem
		summary: - velocity
		velocity = speed * direction
	#End
	Field velocity:TVector2
	
	' ----------------------------------------------------------------------------------------
	' Constructor
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - Create
	#End
	Method New()
		Self.collision.Set(Self.position,Self.size,Self.radius)
	End Method
	
	' ----------------------------------------------------------------------------------------
	'  Show 
	' ----------------------------------------------------------------------------------------	
	#Rem
		summary: - show entity
	#End
	Method Show:Void()
		Self.visible = True
	End Method
	
	' ----------------------------------------------------------------------------------------
	'  Hide 
	' ----------------------------------------------------------------------------------------	
	#Rem
		summary: - hide entity
	#End
	Method Hide:Void()
		Self.visible = False
	End Method
		
	' ----------------------------------------------------------------------------------------
	' SaveCurrentPosition 
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - Store pevieous position to old position vector
	#End
	Method SaveCurrentPosition:Void()
		Self.old_position.Set(Self.position)
	End Method

	' ----------------------------------------------------------------------------------------
	' SetDIrection by actual rotation
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - SetDIrection by actual rotation
	#End
	Method SetDirectionByRotation:Void()
		Self.direction = VecRotate(Self.base_direction,Self.rotation)
	End Method
	
	
	#Rem
		summary: - convert velocity to speed and direction
	#End
	Method ApplyVelocity:Void()
		
		Self.speed = VecLength(Self.velocity)
		Self.direction = VecNormalize(Self.velocity)
	End Method
	
	' ----------------------------------------------------------------------------------------
	' move by delta vector
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - move by delta vector
	#End
	Method Move:Void(delta:TVector2)
		Self.Move(delta.x,delta.y)
	End Method
	
	' ----------------------------------------------------------------------------------------
	' move by delta x,y
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - move by delta x,y
	#End
	Method Move:Void(dx:Float,dy:Float)		
		Self.position = VecAdd(Self.position,New TVector2(dx*AppSpeed()*Self.speed,dy*AppSpeed()*Self.speed))
	End Method
	
	' ----------------------------------------------------------------------------------------
	' move forward
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - move forward
	#End
	Method MoveForward:Void()
		Self.position = VecAdd(Self.position,VecMult(Self.direction,Self.speed*AppSpeed()))

	End Method
		
	' ----------------------------------------------------------------------------------------
	' move to target position (direction isn't changed)
	' Return true when is on target place
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - move to target position (direction isn't changed)
	 Return true when is on target place
	#End
	Method MoveTo:Bool(tx:Float,ty:FLoat)
		
		Local res:Bool=False
		Local dst:TVector2 	= New TVector2(tx,ty)
		Local l:Float		= VecDist(dst,Self.position)
		Local dir:TVector2  = VecDirection(Self.position,dst)

		if (l<AppSpeed()*Self.speed) Then
			Self.position.Set(tx,ty)			
			res = True
		Else
			Self.Move(dir)	
			res = False
		EndIf
		
		Return res
		
	End Method
	
	' ----------------------------------------------------------------------------------------
	' move to target position (direction isn't changed)
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - move to target position (direction isn't changed)
	#End
	Method MoveTo:Bool(dst:TVector2)	
		Return Self.MoveTo(dst.x,dst.y)		
	End Method
	
	#Rem
		summary: - Set forward vector to target position
	#End
	Method LookAt:Void(t:TVector2,dir_to_angle:Bool=False)
		Self.LookAt(t.x,t.y,dir_to_angle)
	End
	' ----------------------------------------------------------------------------------------
	' Set forward vector to target position
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - Set forward vector to target position
	#End
	Method LookAt:Void(tx:Float,ty:FLoat,dir_to_angle:Bool=False)
		
	
		Local dst:TVector2 	= New TVector2(tx,ty)
		Local l:Float		= VecDist(dst,Self.position)
		Self.direction 		= VecNormalize(VecSub(dst,Self.position))
		
		If dir_to_angle Then
			Self.rotation = VecAngleToClockwise(Self.direction,Self.base_direction)
		EndIf
		
	End Method
	
	' ----------------------------------------------------------------------------------------
	' Check collision
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - Check collision
	#End
	Method CollideWith:Bool(sprite:TEntity)
		Local res:Bool = False
		Local p:TVector2 = Self.position.Copy()		
		Local d:Float =  VecDist(Self.position,sprite.position)
			If d<(Self.collision.radius+sprite.collision.radius) Then
				res = True
			Else
				res = False
			EndIf
		Return res
	End MEthod
	' ----------------------------------------------------------------------------------------
	' Check collision
	' ----------------------------------------------------------------------------------------
	#Rem
		summary: - Handle collision with other entity
	#End
	Method HandleCollisionWith:Void(entity:TEntity)

		' no handling'
		If entity.collision_type=COLLISION_TYPE_NONE Then Return

		If Self.collision_type=COLLISION_TYPE_CIRCLE Then 
		
			' BOX collision type
			If entity.collision_type=COLLISION_TYPE_BOX Then 

				Local halfW : Float = entity.collision.size.x / 2.0
				Local halfH : Float = entity.collision.size.y / 2.0

				If Abs( self.position.x - entity.position.x ) < ( halfW + Self.radius ) And Abs( self.position.y - entity.position.y ) < ( halfH + Self.radius )
					
					If Abs( self.old_position.x - entity.position.x ) < ( halfW + Self.radius ) Then
						If self.old_position.y < entity.position.y Then 
							self.position.y = entity.position.y - ( halfH + Self.radius )
						EndIf
						If self.old_position.y > entity.position.y Then 
							self.position.y = entity.position.y + ( halfH + Self.radius )
						EndIf
					Endif
				
					If Abs( self.old_position.y - entity.position.y ) < ( halfH + Self.radius ) Then
						If self.old_position.x < entity.position.x Then 
							self.position.x = entity.position.x - ( halfW + Self.radius )
						EndIf
						If self.old_position.x > entity.position.x Then 
							self.position.x = entity.position.x + ( halfW + Self.radius )
						EndIf
					Endif
				Endif
			EndIf

			' CIRCLE collision type
			If entity.collision_type=COLLISION_TYPE_CIRCLE Then 
				Local dx : Float = Self.position.x - entity.position.x
				Local dy : Float = Self.position.y - entity.position.y
				Local r : Float = Sqrt(( dx * dx ) + ( dy * dy ))
				Local totalR:Float = entity.radius + Self.radius
				If r < totalR
					Local pDir:Float = ATan2( dy, dx )
					Self.position.x = entity.position.x + ( Cos( pDir ) * totalR )
					Self.position.y = entity.position.y + ( Sin( pDir ) * totalR )
				Endif
			EndIf

		EndIf

		If Self.collision_type=COLLISION_TYPE_BOX Then 

		EndIf


	End Method

	
		
	Method TurnToTarget:Void(faceThis:TVector2, turnSpeed:Float)
	
	
	
		Local t:TVector2 = VecSub(faceThis,Self.position)
		Local a_dir:Float = ATan2(Self.direction.x , Self.direction.y)  - ATan2(t.x , -t.y)
		
		Local desiredAngle:Float = ATan2(t.x,-t.y)
		var1 = desiredAngle
		Local difference:Float = WrapAngle180(desiredAngle - Self.rotation)
		var2 = difference
		var3 = a_dir
		
		If difference>0 Then
			Self.rotation = Self.rotation + Abs(difference)*turnSpeed
		EndIf
		
		If difference<0 Then
			Self.rotation = Self.rotation - Abs(difference)*turnSpeed
		EndIf
		
		Self.rotation = WrapAngle360(Self.rotation)		
		Self.SetDirectionByRotation()

		
	End Method
	
End Class





